﻿using Farkhod.BulkImageResizer.Helpers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Farkhod.BulkImageResizer
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        System.Windows.Forms.OpenFileDialog openFileDialog1;
        private bool m_programStarted = false;
        public MainWindow()
        {
            InitializeComponent();
            Initialize();
            LoadUserSettings();
            PopulateDestinationFolder();
            m_programStarted = true;
        }

        private void Initialize()
        {
            vbProgress.Visibility = System.Windows.Visibility.Hidden;
            this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
            this.openFileDialog1.Multiselect = true;
            this.openFileDialog1.Filter = "Images (*.jpg, *.png, *.bmp)|*.jpg*;*.png;*.bmp";
            this.openFileDialog1.Title = Properties.Resources.TITLE_PLEASE_SELECT_IMAGE_FILES;
            //txtSourceFolder.Text = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        }

        private void LoadUserSettings()
        {
            try
            {
                if (Properties.Settings.Default.IsMaximised)
                    WindowState = WindowState.Maximized;
                else
                    WindowState = System.Windows.WindowState.Normal;

                this.Top = Properties.Settings.Default.Top;
                this.Left = Properties.Settings.Default.Left;
                this.Height = Properties.Settings.Default.Height;
                this.Width = Properties.Settings.Default.Width;

                txtSourceFolder.Text = Properties.Settings.Default.SOURCE_FOLDER;
                txtDestinationFolder.Text = Properties.Settings.Default.DESTINATION_FOLDER;
                expander.IsExpanded = Properties.Settings.Default.SETTINGS_OPEN;
                txtDefDstFolderName.Text = Properties.Settings.Default.DEFAULT_DESTINATION_FOLDER;
                txtDefPostfixFileNames.Text = Properties.Settings.Default.DEFAULT_POSTFIX_DESTINATION_FILE_NAMES;
                if (Properties.Settings.Default.RESIZE_BY_PERCENTAGE)
                    rbPercentage.IsChecked = true;
                else
                    rbSize.IsChecked = true;

                slPercent.Value = Properties.Settings.Default.PERCENTAGE_VALUE;
                udImageHeight.Value = Properties.Settings.Default.TO_HEIGHT;
                udImageWidth.Value = Properties.Settings.Default.TO_WIDTH;
            }
            catch (Exception ex)
            {
                ShowMessageInStatusBar(string.Format(Properties.Resources.MSG_EXCEPTION_OCCURED_WHILE, "loading app settings", ex.Message));
            }
        }

        private void btnSourceFolder_Click(object sender, RoutedEventArgs e)
        {
            string sourceFolderPath = string.Empty;
            sourceFolderPath = GetFolderPath(Properties.Resources.STATUS_SELECT_SRC_FOLDER);
            if (!string.IsNullOrEmpty(sourceFolderPath))
            {
                txtSourceFolder.Text = sourceFolderPath;
                PopulateDestinationFolder();
            }
        }

        private void PopulateDestinationFolder()
        {
            if (!string.IsNullOrWhiteSpace(txtSourceFolder.Text))
            {
                if (txtSourceFolder.Text.EndsWith(@"\"))
                    txtDestinationFolder.Text = String.Concat(txtSourceFolder.Text, txtDefDstFolderName.Text);
                else
                    txtDestinationFolder.Text = String.Concat(txtSourceFolder.Text, @"\", txtDefDstFolderName.Text);
            }
        }

        private void btnDestinationFolder_Click(object sender, RoutedEventArgs e)
        {
            string destinationFolderPath = string.Empty;
            destinationFolderPath = GetFolderPath(Properties.Resources.STATUS_SELECT_DST_FOLDER);
            if (!string.IsNullOrEmpty(destinationFolderPath))
                txtDestinationFolder.Text = destinationFolderPath;
        }

        private string GetFolderPath(string title)
        {
            string result = string.Empty;

            try
            {
                using (FolderBrowserDialog dialog = new FolderBrowserDialog())
                {
                    dialog.Description = title;
                    dialog.ShowNewFolderButton = false;
                    dialog.RootFolder = Environment.SpecialFolder.MyComputer;
                    if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        result = dialog.SelectedPath;
                }
            }
            catch (Exception ex)
            {
                ShowMessageInStatusBar(ex.Message);
                result = string.Empty;
            }

            return result;
        }

        private async void btnResize_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtSourceFolder.Text))
            {
                ShowMessageInStatusBar(Properties.Resources.MSG_PLS_SEL_SRC_FLDR_PATH);
                return;
            }

            if (string.IsNullOrWhiteSpace(txtDestinationFolder.Text))
            {
                ShowMessageInStatusBar(Properties.Resources.MSG_PLS_SEL_DST_FLDR_PATH);
                return;
            }

            int height = 0, width = 0;
            if (rbSize.IsChecked == true)
            {
                if (udImageHeight.Value == 0 && udImageWidth.Value == 0)
                {
                    ShowMessageInStatusBar(Properties.Resources.MSG_PLS_SET_CORRECT_IMG_DIMENSION_VALUES);
                    return;
                }
                height = (int)udImageHeight.Value;
                width = (int)udImageWidth.Value;
            }
            string postfixToAdd = txtDefPostfixFileNames.Text;
            ShowMessageInStatusBar(Properties.Resources.STATUS_WORKING);
            vbProgress.Visibility = System.Windows.Visibility.Visible;
            CreateDestinationFolderIfNotExist(txtDestinationFolder.Text);
            if (rbPercentage.IsChecked == true)
                await GenerateThumbs(txtSourceFolder.Text, txtDestinationFolder.Text, postfixToAdd, (int)slPercent.Value);
            else
                await GenerateThumbs(txtSourceFolder.Text, txtDestinationFolder.Text, postfixToAdd, 0, height, width);

            ShowMessageInStatusBar(Properties.Resources.STATUS_DONE);
            vbProgress.Visibility = System.Windows.Visibility.Hidden;
        }

        private void CreateDestinationFolderIfNotExist(string destinationFolderPath)
        {
            if (!Directory.Exists(destinationFolderPath))
                Directory.CreateDirectory(destinationFolderPath);
        }

        private async Task GenerateThumbs(string folderPath, string outputFolerPath, string postfixToAdd, int percent, int height = 0, int width = 0)
        {
            await Task.Factory.StartNew(() =>
                {
                    IEnumerable<string> fileNames = Directory.EnumerateFiles(folderPath).Select(fn => System.IO.Path.GetFileName(fn));
                    //IEnumerable<string> fileNames = Directory.EnumerateFiles(folderPath, "*.*", SearchOption.AllDirectories);

                    string _folderPath = folderPath;
                    string _postFixToAdd = postfixToAdd;
                    int _percent = percent;
                    int _height = height;
                    int _width = width;
                    string result = string.Empty;
                    Parallel.ForEach(fileNames,
                            fileName =>
                            {
                                string _fileName = System.IO.Path.GetFileName(fileName);
                                FileInfo fileInfo = new FileInfo(fileName);
                                string _fullPath = fileInfo.DirectoryName;
                                //if (_height == 0 && _width == 0)
                                //    result = FileHelper.Instance.SaveResizedImage(_fullPath, _fileName, outputFolerPath, string.Concat(_fileName.Substring(0, _fileName.Length - 4), _postFixToAdd, _fileName.Substring(_fileName.Length - 4, 4)), _percent);
                                //else
                                //    result = FileHelper.Instance.SaveResizedImage(_fullPath, _fileName, outputFolerPath, string.Concat(_fileName.Substring(0, _fileName.Length - 4), _postFixToAdd, _fileName.Substring(_fileName.Length - 4, 4)), _height, _width);
                                if (_height == 0 && _width == 0)
                                    result = FileHelper.Instance.SaveResizedImage(_folderPath, fileName, outputFolerPath, string.Concat(fileName.Substring(0, fileName.Length - 4), _postFixToAdd, fileName.Substring(fileName.Length - 4, 4)), _percent);
                                else
                                    result = FileHelper.Instance.SaveResizedImage(_folderPath, fileName, outputFolerPath, string.Concat(fileName.Substring(0, fileName.Length - 4), _postFixToAdd, fileName.Substring(fileName.Length - 4, 4)), _height, _width);

                                if (result != Globals.RESIZE_AND_SAVE_IMAGE_SUCCESSFUL_RESULT)
                                    ShowMessageInStatusBar(result);
                                else
                                    ShowMessageInStatusBar(fileName + " resized successfully."); 
                            });
                });
        }

        private void ShowMessageInStatusBar(string message)
        {
            Dispatcher.Invoke(new Action(() => { tbMessage.Text = message; }));
        }

        private void slPercent_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (m_programStarted)
            {
                if (slPercent.Value > 100)
                    ShowMessageInStatusBar(string.Format(Properties.Resources.MSG_IMG_ENLARGE_TO_N_PERCENT, slPercent.Value.ToString()));
                else if (slPercent.Value == 100)
                    ShowMessageInStatusBar(string.Format(Properties.Resources.MSG_IMG_WONT_RESIZE, slPercent.Value.ToString()));

                else
                    ShowMessageInStatusBar(string.Format(Properties.Resources.MSG_IMG_REDUCE_TO_N_PERCENT, slPercent.Value.ToString()));
            }
        }

        private void SaveUserSettings()
        {
            try
            {
                if (WindowState == WindowState.Maximized)
                    Properties.Settings.Default.IsMaximised = true;
                else
                    Properties.Settings.Default.IsMaximised = false;

                Properties.Settings.Default.Top = this.Top;
                Properties.Settings.Default.Left = this.Left;
                Properties.Settings.Default.Height = this.Height;
                Properties.Settings.Default.Width = this.Width;

                Properties.Settings.Default.SOURCE_FOLDER = txtSourceFolder.Text;
                Properties.Settings.Default.DESTINATION_FOLDER = txtDestinationFolder.Text;
                Properties.Settings.Default.DEFAULT_DESTINATION_FOLDER = txtDefDstFolderName.Text;
                Properties.Settings.Default.SETTINGS_OPEN = expander.IsExpanded;
                Properties.Settings.Default.DEFAULT_POSTFIX_DESTINATION_FILE_NAMES = txtDefPostfixFileNames.Text;
                Properties.Settings.Default.RESIZE_BY_PERCENTAGE = (bool)rbPercentage.IsChecked;
                Properties.Settings.Default.PERCENTAGE_VALUE = (int)slPercent.Value;
                Properties.Settings.Default.TO_HEIGHT = (int)udImageHeight.Value;
                Properties.Settings.Default.TO_WIDTH = (int)udImageWidth.Value;
                Properties.Settings.Default.Save();
            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show(ex.Message);
            }
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            SaveUserSettings();
        }
    }
}
